﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Blank.Http.EventArg;
using System.Net;
using System.Net.Cache;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Text.RegularExpressions;
using System.Drawing;
using Blank.CommonLib.Utils;

namespace Blank.Http
{
    public abstract class ISite
    {
        private CookieContainer _Cookie = new CookieContainer();
        private RequestCachePolicy _DefCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
        private bool _AllowAutoRedirect = true;
        private bool _isSetRandonIp = false;
        private string _randonIp = string.Empty;
        private Logger _ILogger = Logger.GetInstance();
        private string _myWebAddress;
        protected const string DefGetCommand = "GET";
        public const int DefMidfielderTime = 45;
        protected const string DefPostCommand = "POST";
        protected const string DefUserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)";
        #region Properties
        /// <summary>
        /// 302自动跳转
        /// </summary>
        public bool AllowAutoRedirect
        {
            get { return _AllowAutoRedirect; }
            set { _AllowAutoRedirect = value; }
        }
        /// <summary>
        /// 证书路径
        /// </summary>
        public string CerPath
        {
            get;
            set;
        }
        /// <summary>
        /// 证书集合
        /// </summary>
        public X509CertificateCollection ClentCertificates
        {
            get;
            set;
        }
        public CookieContainer Cookie
        {
            get
            {
                return this._Cookie;
            }
            protected set
            {
                this._Cookie = value;
            }
        }
        public CookieCollection CookieCollection
        {
            get;
            set;
        }
        /// <summary>
        /// 应用程序缓存要求
        /// </summary>
        public RequestCachePolicy DefCachePolicy
        {
            get
            {
                return this._DefCachePolicy;
            }
        }
        /// <summary>
        /// 编码格式
        /// </summary>
        public Encoding Encoding
        {
            get;
            set;
        }
        public string Host
        {
            get;
            set;
        }

        /// <summary>
        /// 日志记录者
        /// </summary>
        public Logger ILogger
        {
            get { return _ILogger; }
            set { _ILogger = value; }
        }
        /// <ummary>
        /// 是否构建随机IP
        /// </summary>
        public bool IsSetRandonIp
        {
            get { return _isSetRandonIp; }
            set { _isSetRandonIp = value; }
        }
        public virtual string LastReadAddress
        {
            get;
            protected set;
        }
        public virtual string MyWebAddress
        {
            get { return _myWebAddress; }
            protected set { this._myWebAddress = value; }
        }
        public virtual int WebTimeOut
        {
            get
            {
                return 60000;
            }
        }
        public virtual string LastReadHtml { get; protected set; }
        public WebProxy WebProxy
        {
            get;
            set;
        }
        public string ProxyIp
        {
            get;
            set;
        }
        public string ProxyPwd
        {
            get;
            set;
        }
        public string ProxyUserName
        {
            get;
            set;
        }
        /// <summary>
        /// 获取之前构建的随机IP
        /// </summary>
        public string RandonIp
        {
            get { return _randonIp; }
            private set { _randonIp = value; }
        }
        #endregion
        public event EventHandler<InputValidateCodeEventArgs> InputValidateCodeCompleted;
        public event EventHandler<ShowMessageEventArgs> OnShowMessageCompleted;
        protected virtual HttpWebRequest CreateGetRequest(string addressFormat, bool isLogLast = true)
        {
            string requestUriString = string.Format(addressFormat, this.MyWebAddress);
            if (isLogLast)
            {
                this.LastReadAddress = requestUriString;
            }
            HttpWebRequest request = WebRequest.Create(requestUriString) as HttpWebRequest;
            request.Method = "GET";
            request.UserAgent = DefUserAgent;
            request.CachePolicy = this.DefCachePolicy;
            request.CookieContainer = this.Cookie;
            request.Timeout = this.WebTimeOut;
            request.ReadWriteTimeout = this.WebTimeOut;
            request.KeepAlive = true;
            request.AllowAutoRedirect = this.AllowAutoRedirect;
            this.SetCer(request);
            this.SetProxy(request);
            this.SetRandowIp(request);
            return request;
        }
        protected virtual HttpWebRequest CreatePostRequest(string addressFormat, bool isLogLast = true)
        {
            string requestUriString = string.Format(addressFormat, this.MyWebAddress);
            if (isLogLast)
            {
                this.LastReadAddress = requestUriString;
            }
            HttpWebRequest request = WebRequest.Create(requestUriString) as HttpWebRequest;
            request.Method = "POST";
            request.UserAgent = DefUserAgent;
            request.CachePolicy = this.DefCachePolicy;
            request.CookieContainer = this.Cookie;
            request.Timeout = this.WebTimeOut;
            request.ReadWriteTimeout = this.WebTimeOut;
            request.KeepAlive = true;
            request.AllowAutoRedirect = this.AllowAutoRedirect;
            this.SetCer(request);
            this.SetProxy(request);
            return request;
        }
        /// <summary>
        /// 成功获取验证码
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnInputValidateCode(InputValidateCodeEventArgs e)
        {
            if (this.InputValidateCodeCompleted != null)
            {
                this.InputValidateCodeCompleted(this, e);
            }
        }
        /// <summary>
        /// 输出日志
        /// </summary>
        /// <param name="message"></param>
        public virtual void ShowNormalMessage(string format, params object[] args)
        {
            ShowNormalMessage(string.Format(format, args), Color.Black);
        }
        public virtual void ShowNormalMessage(string message, Color messageColor)
        {
            if (OnShowMessageCompleted != null)
            {
                OnShowMessageCompleted(this, new ShowMessageEventArgs(messageColor, message));
            }
            if (this.ILogger != null)
                this.ILogger.OutPutInfomationMessage(message);
        }
        public virtual void ShowErrorMessage(Exception ex)
        {
            if (OnShowMessageCompleted != null)
            {
                OnShowMessageCompleted(this, new ShowMessageEventArgs(Color.Red, ex.Message));
            }
            if (this.ILogger != null)
                this.ILogger.OutPutException(ex);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="certificate"></param>
        /// <param name="chain"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        protected virtual bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }
        /// <summary>
        /// 加载目标网站证书
        /// </summary>
        /// <param name="request"></param>
        protected void SetCer(HttpWebRequest request)
        {
            if (string.IsNullOrEmpty(this.CerPath))
            {
                this.SetCerList(request);
            }
            else
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(this.CheckValidationResult);
                this.SetCerList(request);
                request.ClientCertificates.Add(new X509Certificate(this.CerPath));
            }
        }
        protected void SetCerList(HttpWebRequest request)
        {
            if (this.ClentCertificates != null && this.ClentCertificates.Count > 0)
            {
                foreach (X509Certificate clentCertificate in this.ClentCertificates)
                {
                    request.ClientCertificates.Add(clentCertificate);
                }
            }
        }
        /// <summary>
        /// 使用代理
        /// </summary>
        /// <param name="request"></param>
        protected void SetProxy(HttpWebRequest request)
        {
            if (!string.IsNullOrEmpty(this.ProxyIp))
            {
                if (!this.ProxyIp.Contains(":"))
                {
                    this.WebProxy = new WebProxy(this.ProxyIp, false);
                }
                else
                {
                    string[] strArrays = this.ProxyIp.Split(':');
                    this.WebProxy = new WebProxy(strArrays[0].Trim(), Convert.ToInt32(strArrays[1].Trim()));
                }
                this.WebProxy.Credentials = new NetworkCredential(this.ProxyUserName, this.ProxyPwd);
                request.Proxy = this.WebProxy;
                request.Credentials = CredentialCache.DefaultCredentials;
            }
            else if (this.WebProxy != null)
            {
                request.Proxy = this.WebProxy;
            }
        }
        /// <summary>
        /// 构造随机IP
        /// </summary>
        /// <param name="request"></param>
        protected void SetRandowIp(HttpWebRequest request)
        {
            if (this.IsSetRandonIp)
            {
                Random r = new Random();
                int a = r.Next(100, 255);
                int b = r.Next(100, 255);
                int c = r.Next(100, 255);
                int d = r.Next(100, 255);
                if (!string.IsNullOrEmpty(this.RandonIp))
                {
                    this.RandonIp = a + "." + b + "." + c + "." + d;
                    request.Headers.Add("X-FORWARDED-FOR", this.RandonIp);
                    request.Headers.Add("CLIENT-IP", this.RandonIp);
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool CheckUrl(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }
            return new Regex(@"https?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", RegexOptions.IgnoreCase).IsMatch(str);
        }
    }
}
